package utils;

import org.apache.commons.lang.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;

/**
 * @author 杨纪聪
 * @version 1.0
 * @date 2022/3/1
 */
public class StringUtil {

    private static final String REQUEST_NO_PREFIX = "HBJ";
    private static final String MARK_1 = "\\?";
    private static final String MARK_2 = "&";
    private static final String MARK_3 = "=";
    private static final int MIN_ARRAY_LEN = 2;
    private static final int DIVIDE_INTO_PAIRS = 2;

    private static final Pattern MOBILE = Pattern.compile("^1\\d{10}$");

    /**
     * 生成流水号
     *
     * @return 流水号
     */
    public static String getSerialNo() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        Date date = new Date();
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        String dateStr = formatter.format(date);
        return REQUEST_NO_PREFIX + dateStr + uuid;
    }

    /**
     * 脱敏处理
     *
     * @param number     待脱敏参数
     * @param startIndex 起始字符下标
     * @param endIndex   结束字符下标
     * @return 脱敏后的结果
     */
    public static String numberEncry(String number, int startIndex, int endIndex) {
        char[] charArray = number.toCharArray();
        if (startIndex < 0 || endIndex < 0 || startIndex > number.length() - 1 || endIndex > number.length() - 1) {
            String errorMsg = String.format("脱敏处理异常！字符长度=%s startIndex=%s endIndex=%s", number.length(), startIndex, endIndex);
            throw new RuntimeException(errorMsg);
        }
        for (int i = startIndex; i <= endIndex; i++) {
            charArray[i] = '*';
        }
        return String.valueOf(charArray);
    }

    /**
     * 解析url->map
     *
     * @param url
     * @return
     */
    public static Map<String, String> getUrlParams(String url) {
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isEmpty(url) || !url.contains("?")) {
            return map;
        }
        String[] parts = url.split(MARK_1, DIVIDE_INTO_PAIRS);
        if (parts.length < MIN_ARRAY_LEN) {
            return map;
        }
        String parsedStr = parts[1];
        if (parsedStr.contains(MARK_2)) {
            String[] multiParamObj = parsedStr.split(MARK_2);
            for (String obj : multiParamObj) {
                parseBasicParam(map, obj);
            }
            return map;
        }
        parseBasicParam(map, parsedStr);
        return map;

    }

    /**
     * 将    YY = XX 的字符串放入map集合
     * YY 为key
     * XX 为value
     * @param map
     * @param str
     */
    private static void parseBasicParam(Map<String, String> map, String str) {
        String[] paramObj = str.split(MARK_3);
        if (paramObj.length < MIN_ARRAY_LEN) {
            return;
        }
        map.put(paramObj[0], paramObj[1]);
    }

    /**
     * 分转元
     *
     * @param price  price
     * @param format format e.g. 0.00
     */
    public static String fenToYuan(Long price, String format) {
        DecimalFormat decimalFormat = new DecimalFormat(format);
        BigDecimal result = BigDecimal.valueOf(price).divide(new BigDecimal(100));
        decimalFormat.format(result);
        return decimalFormat.format(result);
    }

    /**
     * 字符串转化成为16进制字符串
     *
     * @param s
     * @return
     */
    public static String strToHexString(String s) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String hex = Integer.toHexString(ch);
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 判断是否是手机号
     *  通过正则校验
     * @param mobile
     * @return
     */
    public static boolean isMobile(String mobile) {
        return MOBILE.matcher(mobile).matches();
    }

    public static void main(String[] args) {
        String sadfhuwe = convert("1B2A3D1A4A");


    }

    /**
     * 一个字符串的自定义排序问题，简单来说就是分页查询时能够按照某个字段实现类似 ["1A-2B", "2A-2B", .... , "11A-2B"]的排序效果
     * （如果使用mysql或者java的默认排序，会变成"1A-2B", "11A-2B", "2A-2B"这样，这是逐字符排序导致的）
     * 根据鱼皮的建议，考虑到实际的业务需求，字符串中出现的数字一般不会很多位，且该字段不会特别长，于是采用了一下解决方案：
     * 将65535（char的最大值）以内的连续数字转为对应的char字符替换原来的连续数字，新增时作为排序字段保存到数据库，
     * 获取列表时直接根据该排序字段排序即可，解决了先分页查询后排序的数据误差问题，实测可用。
     * @param fileName
     * @return
     */
    public static String convert(String fileName) {
        char[] cs = fileName.toCharArray();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < cs.length;) {
            if (cs[i] < '0' || cs[i] > '9') {
                builder.append(cs[i++]);
            } else {
                StringBuilder numBuilder = new StringBuilder();
                while (i < cs.length && cs[i] >= '0' && cs[i] <= '9') {
                    numBuilder.append(cs[i++]);
                }
                // 如果超出5位数或者超过65535（char最大值）则当做多个字符处理，否则转为数字对应的字符拼接
                if (numBuilder.length() > 5) {
                    builder.append(numBuilder);
                    continue;
                }
                int num = Integer.parseInt(numBuilder.toString());
                if (num > 65535) {
                    builder.append(numBuilder);
                } else {
                    builder.append((char) num);
                }
            }
        }
        return builder.toString();
    }

}
